//获取accessToken   有效期2小时 唯一

//读取本地文件  readAccessToken

// 请求access_token 存入本地

//本地有文件

// 读取本地文件 判断是否过期 isValidAccessToken
// 过期
// 重新获取 getAccessToken 
// 覆盖之前的文件 saveAccessToken
// 没有过期
// 直接使用 

//本地无文件
// 获取access_token(getAccessToken) 保存下来(saveAccessToken)

const {appID,appsecret} = require('../config')
/*
request
request-promise-native  返回值是一个promise对象
*/
const rp = require('request-promise-native')
const api = require('../utils/api.js')
const {writeFileAsync,readFileAsync} = require('../utils/tool_.js')
const menu = require('./menu.js')
class Wechat {
    constructor () {

    }
   // 从微信服务获取access_token
    getAccessToken () {
       //https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
        //定义请求的地址
        const url = `${api.accessToken}&appid=${appID}&secret=${appsecret}`;
        //发送请求
        
        return new Promise((resolve, reject) => {
            rp({method: 'GET', url, json: true})
            .then(res => {
                // console.log(res);
                /*
                { access_token: '13_DGddvcTZ4HPm8tjcHGwnDAtk9LbNQMA_h_D3ffxcncMsJwGgfCUaLChd_pPjHb4ilxeyOr8adZ9iOv14unJyK7q4qPYO8ekPPCuXvMDu-t9hBURiwKWriNuP4HzvEVNQ2JoATXwCGrOwqwjgKJUaABAXWH',
                    expires_in: 7200 }
                */
                //设置access_token的过期时间 -5分钟
                res.expires_in = Date.now() + (res.expires_in - 300) * 1000;
                //将promise对象状态改成成功的状态
                resolve(res);
            }).catch(err => {
                console.log('获取access_token出错：',err);
                //将promise对象状态改成失败的状态
                reject('getAccessToken方法出了问题：' + err);
            })
        })
   }

   //保存到本地文件
   saveAccessToken (accessToken) {return writeFileAsync(accessToken, 'access_token.txt');}

   //读取(readAccessToken)
   readAccessToken () { return readFileAsync('access_token.txt')} 
   
   
// 读取本地文件 判断是否过期 isValidAccessToken
    isValidAccessToken(data) {
        //验证传入的参数是否是有效的
        if(!data && !data.access_token && !data.expires_in){
            //acess_token无效
            return false
        }

        //检测access_token是否在有效期内
        return data.expires_in > Date.now()
        //如果过期时间大于现在时间 返回ture
    }

// 用来获取没有过期的access_token
    fetchAccessToken(){
        if (this.access_token && this.expires_in && this.isValidAccessToken(this)){
          //token有效 直接使用
            return Promise.resolve({
                access_token: this.access_token,
                express_in: this.expires_in
            })
        }
        //是fetchAccessToken的返回值
        return this.readAccessToken().then(async res => {
                    //本地有文件
                    if(this.isValidAccessToken(res)){
                        //有效的
                        console.log('本地access_token 有效')
                        return Promise.resolve(res)
                    } else{
                        // //重新获取 getAccessToken 
                        // const res = await this.getAccessToken()
                        // //保存至本地
                        // await this.saveAccessToken(res)
                        // // resolve(res)
                        // return Promise.resolve(res)
                        return Promise.reject('access_token 过期')
                    }
                })
                .catch(async err => {
                    //重新获取 getAccessToken 
                    console.log('刷新access_token')
                    const res = await this.getAccessToken()
                    //保存至本地
                    await this.saveAccessToken(res)
                    //将access_token成功的内容挂载到this上
                    this.access_token = res.access_token
                    this.expires_in = res.expires_in
                    // resolve(res)
                    return Promise.resolve(res)
                })
    }
    // 查询菜单
    queryMenu(){
        return new Promise(async (resolve,reject)=>{
            try {
                let {access_token} = await this.fetchAccessToken()
                // http请求方式: GET（请使用https协议）https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN
                let url = `${api.menu.query}access_token=${access_token}`
                let res = await rp({method:'GET',url,json:true})
                console.log(res,'>>>>>>查询菜单')
                resolve(res)
            } catch (error) {
                console.log('>>>>查询菜单失败')
                reject(error)
            }
        })
    }
     // 创建菜单
    createMenu(){
        return new Promise( async (resolve,reject)=>{
            try {
                let {access_token} = await this.fetchAccessToken()
                // https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
                let url = `${api.menu.create}access_token=${access_token}`
                let res = await rp({method:'POST',url,json:true,body:menu})
                console.log(res,'>>>>>创建菜单成功')
                resolve(res)
            } catch (error) {
                console.log('>>>>菜单创建失败')
              reject(error)  
            }
        })
    }
    // 删除菜单
    deleteMenu(){
        return new Promise(async (resolve,reject)=>{
            try {
                let {access_token} = await this.fetchAccessToken()
                // http请求方式：GET https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
                let url = `${api.menu.delete}access_token=${access_token}`
                let res = await rp({method:'GET',url,json:true})
                console.log('>>>>菜单删除成功')
                resolve(res)
            } catch (error) {
                console.log('>>>>菜单删除失败')
                reject(error)
            }
        })
    }
    //获取jsapi ticket
    getTicket(){
        return new Promise(async (resolve,reject)=>{
             try {
                 // https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
                 let {access_token} = await this.fetchAccessToken()
                 let url = `${api.ticket}&access_token=${access_token}`
                 let {ticket,expires_in} = await rp({method:'GET',url,json:true})
                 resolve({
                     ticket,
                     expires_in: Date.now() + (expires_in - 300) * 1000
                 })
             } catch (error) {
                 console.log('>>>> ticket 获取失败')
                 reject(error)
             }
        })
    }
    saveTicket(ticket){
        return writeFileAsync(ticket,'ticket.txt')
    }
    readTicket(){
        return readFileAsync('ticket.txt')
    }
    // 验证ticket
    isValidTicket(data){
        if(!data || !data.ticket || !data.expires_in) return false
        return data.expires_in > Date.now()
    }
    // 获取有效的 ticket 
    fetchTicket(){
        if(this.ticket && this.ticket_expires_in && this.isValidTicket(this)){
            return Promise.resolve({
                ticket:this.ticket,
                expires_in:this.ticket_expires_in
            })
        }
        return new Promise(async(resolve,reject)=>{
           
            try {
               let  res = await this.readTicket()
               if(this.isValidTicket(res)){
                   console.log('本地 ticket 有效 >>>>')
                   resolve(res)
               }else{
                  throw new Error('本地 ticket 无效 <<<<<')
                }
            } catch (error) {
                console.log(error)
                try {
                    console.log('刷新ticket >>>>>')
                    let {ticket,expires_in} = await this.getTicket()
                    await this.saveTicket({ticket,expires_in},'ticket.txt')
                    this.ticket = ticket
                    this.ticket_expires_in = expires_in
                    resolve({ticket,expires_in})
                } catch (error) {
                    console.log('获取ticket 失败 <<<<<<')
                    reject(error)
                }
            }
        })
    }
    // 网页授权获取 网页access_token openid
    getOauth2Token(code){
        // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
        return new Promise(async(resolve,reject)=>{
            try {
                let url = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appID}&secret=${appsecret}&code=${code}&grant_type=authorization_code`
                let res = await rp({mehtod:'GET',url,json:true})
                if(res.access_token && res.openid){
                    res.expires_in = Date.now() + (res.expires_in - 300) * 1000;
                    await writeFileAsync(res,'openid.txt')
                    resolve(res)
                }else{
                    reject('参数错误 code is not defined')
                }
            } catch (error) {
                reject(error)
            }
        })
    }
    // 刷新用户授权access_token
    refreshOauthToken(refresh_token){
        return new Promise(async(reject,resolve)=>{
            // https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
            try {
                let url = `https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=${appID}&grant_type=refresh_token&refresh_token=${refresh_token}`
                let data = await rp({method:'GET',url,json:true}) 
                data.expires_in = Date.now() + (data.expires_in - 300) * 1000
                await writeFileAsync(data,'openid.txt')
                resolve(data)
            } catch (error) {
                reject(error)
            }
        })
    }
    // 获取有效的 openid access_token
    fetchOpenId(code){
        return new Promise(async(resolve,reject)=>{
            try {
                let data = await readFileAsync('openid.txt')
                if(this.isValidOpenId(data)){
                    resolve({
                        openid:data.openid,
                        access_token:data.access_token
                    })
                }else{
                    //过期
                    let {openid,access_token} = await this.refreshOauthToken(data.refresh_token)
                    resolve({
                        openid,
                        access_token
                    })
                }
            } catch (error) {
                // 本地没有 openid
                try {
                    let {openid,access_token} = await this.getOauth2Token(code)
                    resolve(openid,access_token)
                } catch (error) {
                    reject(error)
                }
            }
        })
    }
    isValidOpenId(data){
        if(!data || !data.openid || !data.expires_in) return false
        return data.expires_in > Date.now()
    }
    // 获取用户信息
    getUserInfo(){
        // https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
        return new Promise(async(resolve,reject)=>{
            try {
                let {access_token,openid,expires_in} = await readFileAsync('openid.txt')
                if(this.isValidOpenId({openid,expires_in})){
                    let url = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}&lang=zh_CN`
                    let res = await rp({method:'GET',url,json:true})
                    resolve(res)
                }else{
                    reject('用户access_token 失效')
                }
            } catch (error) {
                reject(error)
            }
        })
    }
}
const wechat = new Wechat()

wechat.queryMenu().then(res => {
    if(!res.is_menu_open){
        return wechat.createMenu()
    }else{
        console.log('>>>>公众号自定义菜单已开启')
    }
}).catch(err=>{
    console.log(err,'>>>>公众号自定义菜单出错')
})
module.exports = wechat


